package top.xphu.zip.service.impl;

import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import top.xphu.zip.ZipUtils;
import top.xphu.zip.entiy.HttpClientConfig;
import top.xphu.zip.entiy.Param;
import top.xphu.zip.entiy.ZFileInputStream;
import top.xphu.zip.enums.HttpMethod;
import top.xphu.zip.enums.ParamType;
import top.xphu.zip.service.DownloadFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author xphu
 * @version 1.0
 * @date 2021/7/1 16:24
 */
public class DownloadFileImpl extends DownloadFile {

    public static final MediaType JSON
            = MediaType.parse("application/json; charset=utf-8");


    public DownloadFileImpl() {
        if (httpClient == null) {
            //加同步安全
            synchronized (DownloadFileImpl.class) {
                if (httpClient == null) {
                    //okhttp可以缓存数据....指定缓存路径
                    File sdcache = new File(System.getProperty("user.dir") + "\\temp\\", "cache");
                    //指定缓存大小
                    int cacheSize = 10 * 1024 * 1024;
                    //构建器
                    httpClient = new OkHttpClient.Builder()
                            //连接超时
                            .connectTimeout(15, TimeUnit.SECONDS)
                            //写入超时
                            .writeTimeout(20, TimeUnit.SECONDS)
                            //读取超时
                            .readTimeout(20, TimeUnit.SECONDS)
                            //设置缓存
                            .cache(new Cache(sdcache.getAbsoluteFile(), cacheSize))
                            .build();
                }
            }
        }
    }

    public DownloadFileImpl(HttpClientConfig clientConfig) {
        httpClient = new OkHttpClient.Builder()
                // 连接超时
                .connectTimeout(clientConfig.getConnectTimeout(), TimeUnit.SECONDS)
                // 通话超时
                .callTimeout(clientConfig.getCallTimeout(), TimeUnit.SECONDS)
                .writeTimeout(clientConfig.getWriteTimeout(), TimeUnit.SECONDS)
                .readTimeout(clientConfig.getReadTimeout(), TimeUnit.SECONDS)
                .build();
    }

    /**
     * 执行下载
     * @param fileName
     * @param response
     * @param httpResponse
     * @return
     * @throws Exception
     */
    @Override
    public HttpServletResponse execute(String fileName , Response response, HttpServletResponse httpResponse) throws Exception {
        if (response.isSuccessful()){
            ResponseBody responseBody = response.body();
            assert responseBody != null;
            InputStream inputStream = responseBody.byteStream();
            return super.download(inputStream, fileName, httpResponse);
        }
        return httpResponse;
    }

    /**
     * 执行下载
     * @param fileName
     * @param response
     * @param httpResponse
     * @return
     * @throws Exception
     */
    @Override
    public ZFileInputStream executeToFileInputStream(String fileName , Response response, HttpServletResponse httpResponse) throws Exception {
        ZFileInputStream zfis = new ZFileInputStream();
        if (response.isSuccessful()){
            ResponseBody responseBody = response.body();
            assert responseBody != null;
            InputStream inputStream = responseBody.byteStream();
            zfis.setFileName(fileName);
            zfis.setFileBody(inputStream);
        }
        return zfis;
    }

    /**
     * @param url      下载地址
     * @param fileName 文件名
     * @param response HttpServletResponse
     * @return HttpServletResponse
     * @throws Exception
     */
    @Override
    public HttpServletResponse httpDownload(String url, String fileName, HttpServletResponse response) throws Exception {
        return doGetHttpDownload(url, fileName, response);
    }

    /**
     * @param url       下载地址
     * @param fileName
     * @param param
     * @param paramType
     * @param response
     * @return HttpServletResponse
     */
    @Override
    public HttpServletResponse httpDownload(String url, String fileName, Map<String, String> param, ParamType paramType, HttpServletResponse response) throws Exception {
        return doGetHttpDownload(url, fileName, param, response);
    }

    /**
     * 通过get http请求下载文件
     *
     * @param url   下载地址
     * @param param 参数
     * @return HttpServletResponse
     */

    /**
     * @param url       下载地址
     * @param method    请求方式
     * @param fileName
     * @param param
     * @param paramType
     * @param response
     * @return HttpServletResponse
     */
    @Override
    public HttpServletResponse httpDownload(String url, HttpMethod method, String fileName, Map<String, String> param, ParamType paramType, HttpServletResponse response) throws Exception {
        if (method == HttpMethod.GET) {
            return doGetHttpDownload(url, fileName, param, response);
        }
        if (method == HttpMethod.POST) {
            return doPostHttpDownload(url, fileName, param, paramType, response);
        }
        return response;
    }

    /**
     * @param url       下载地址
     * @param method    请求方式
     * @param fileName
     * @param param
     * @param paramType
     * @param response
     * @return HttpServletResponse
     */
    @Override
    public HttpServletResponse httpDownload(String url, HttpMethod method, String fileName, Param param, ParamType paramType, HttpServletResponse response) throws Exception {
        if (method == HttpMethod.GET) {
            return doGetHttpDownload(url, fileName, param, response);
        }
        if (method == HttpMethod.POST) {
            return doPostHttpDownload(url, fileName, param, paramType, response);
        }
        return response;
    }

    /**
     * 通过get http请求下载文件
     * @param url       下载地址 "http://www.5m4.top/file/15"
     * @param fileName  文件名称 ：default.txt
     * @param httpResponse
     * @return HttpServletResponse
     */
    @Override
    public HttpServletResponse doGetHttpDownload(String url, String fileName, HttpServletResponse httpResponse) throws Exception {
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        Response response = httpClient.newCall(request).execute();
        return execute(fileName, response, httpResponse);
    }

    /**
     * 通过get http请求下载文件
     *
     * @param url       下载地址 "http://www.5m4.top/file/15"
     * @param fileName  文件名称 ：default.txt
     * @param param     参数 <>"id":"12"</>
     * @param httpResponse
     * @return HttpServletResponse
     */
    @Override
    public HttpServletResponse doGetHttpDownload(String url, String fileName, Map<String, String> param, HttpServletResponse httpResponse) throws Exception {
        StringBuilder paramStr = null;
        if (param != null){
            paramStr = new StringBuilder("?");
            for (String key : param.keySet()) {
                paramStr.append(key + "=" + param.get(key) + "&");
            }
        }
        if (StringUtils.isNotBlank(paramStr)){
            url += paramStr;
        }
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        Response response = httpClient.newCall(request).execute();
        return execute(fileName, response, httpResponse);
    }


    /**
     * 通过get http请求下载文件
     *
     * @param url       下载地址 "http://www.5m4.top/file/15"
     * @param fileName  文件名称 ：default.txt
     * @param httpResponse
     * @return ZFileInputStream
     */
    @Override
    public ZFileInputStream doGetHttpDownloadToZFileInputStream(String url, String fileName, HttpServletResponse httpResponse) throws Exception {
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        Response response = httpClient.newCall(request).execute();
        return executeToFileInputStream(fileName, response, httpResponse);
    }

    /**
     * 通过post http请求下载文件
     *
     * @param url   下载地址
     * @return HttpServletResponse
     */
    @Override
    public HttpServletResponse doPostHttpDownload(String url, String fileName, HttpServletResponse httpResponse) throws Exception {
        FormBody body = new FormBody.Builder().build();
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Response response = httpClient.newCall(request).execute();
        return execute(fileName, response, httpResponse);
    }

    /**
     * 通过post http请求下载文件
     *
     * @param url   下载地址
     * @param param 参数
     * @return HttpServletResponse
     */
    @Override
    public HttpServletResponse doPostHttpDownload(String url, String fileName, Map<String, String> param, ParamType paramType, HttpServletResponse httpResponse) throws Exception {
        Request request;
        RequestBody body = null;
        StringBuilder paramStr = null;

        if (paramType == ParamType.FORM){
            FormBody.Builder formBody = new FormBody.Builder();
            for (String key : param.keySet()) {
                formBody.add(key, param.get(key));
            }
            body = formBody.build();
        } else if (paramType == ParamType.JSON){
            body = RequestBody.create(JSON, JSONObject.toJSONString(param));
        }else if (paramType == ParamType.QUERY){
            if (param != null){
                paramStr = new StringBuilder("?");
                for (String key : param.keySet()) {
                    paramStr.append(key + "=" + param.get(key) + "&");
                }
            }
            if (StringUtils.isNotBlank(paramStr)){
                url += paramStr;
            }
        }

        request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Response response = httpClient.newCall(request).execute();
        return execute(fileName, response, httpResponse);
    }

    /**
     * 通过get http请求下载文件
     *
     * @param url   下载地址
     * @param param 参数
     * @return HttpServletResponse
     */
    @Override
    public HttpServletResponse doGetHttpDownload(String url, String fileName, Param param, HttpServletResponse response) throws Exception {
        return doGetHttpDownload(url, fileName, param.toMap(), response);
    }

    /**
     * 通过get http请求下载文件
     *
     * @param url   下载地址
     * @param param 参数
     * @return HttpServletResponse
     */
    @Override
    public HttpServletResponse doPostHttpDownload(String url, String fileName, Param param,ParamType paramType, HttpServletResponse response) throws Exception {
        return doPostHttpDownload(url, fileName, param.toMap(), paramType, response);
    }

}
